package com.newshub.ai.service.impl;

import com.newshub.ai.core.factory.LLMClientFactory;
import com.newshub.ai.core.client.LLMClient;
import com.newshub.ai.util.SqlQueryBuilder;
import com.newshub.ai.util.DataQueryExecutor;
import com.newshub.ai.util.ChartGenerator;
import com.newshub.ai.util.BiPromptProvider;
import com.newshub.ai.model.dto.BiQueryRequest;
import com.newshub.ai.model.dto.ChatRequest;
import com.newshub.ai.model.dto.ChatResponse;
import com.newshub.ai.service.ChatBIService;
import com.newshub.ai.service.ChatBISessionService;
import com.newshub.ai.util.QuestionAnalyzer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * ChatBI 核心服务实现类 - 流式版本
 */
@Slf4j
@Service
public class ChatBIServiceImpl implements ChatBIService {
    
    @Autowired
    private LLMClientFactory llmClientFactory;
    
    @Autowired
    private SqlQueryBuilder sqlQueryBuilder;
    
    @Autowired
    private DataQueryExecutor dataQueryExecutor;
    
    @Autowired
    private ChartGenerator chartGenerator;

    @Autowired
    private BiPromptProvider biPromptProvider;
    
    @Autowired
    private ChatBISessionService sessionService;
    
    @Autowired
    private QuestionAnalyzer questionAnalyzer;
    
    @Override
    public SseEmitter processQueryStream(BiQueryRequest request) {
        log.info("开始处理流式 BI 查询: {} (sessionId: {})", request.getQuery(), request.getSessionId());
        
        SseEmitter emitter = new SseEmitter(60000L); // 60秒超时
        
        // 设置SSE必要的响应头
        emitter.onCompletion(() -> log.info("BI SSE流完成"));
        emitter.onTimeout(() -> log.info("BI SSE流超时"));
        emitter.onError((ex) -> log.error("BI SSE流错误", ex));
        
        CompletableFuture.runAsync(() -> {
            try {
                // 获取对话历史
                List<ChatRequest.ChatMessage> history = sessionService.getHistory(request.getSessionId());
                log.debug("获取到对话历史，共 {} 条消息", history.size());
                
                // 发送开始事件
                emitter.send(SseEmitter.event()
                    .name("start")
                    .data("开始处理 BI 查询..."));
                
                // 1. 生成 SQL（带对话历史）
                emitter.send(SseEmitter.event().name("sql_generation").data("正在生成 SQL 查询..."));
                String sql = generateSqlWithLLM(request.getQuery(), request.getTimeRange(), request.getMaxRecords(), history);
                if (sql == null) {
                    sql = sqlQueryBuilder.buildSqlFromNaturalLanguage(request.getQuery());
                    emitter.send(SseEmitter.event().name("sql_fallback").data("使用规则生成 SQL"));
                } else {
                    emitter.send(SseEmitter.event().name("sql_llm").data("使用 AI 生成 SQL"));
                }
                emitter.send(SseEmitter.event().name("sql_generated").data(sql));
                
                // 2. SQL 安全校验
                if (!sqlQueryBuilder.isValidQuery(sql)) {
                    emitter.send(SseEmitter.event().name("error").data("SQL 查询不安全，已拒绝执行"));
                    emitter.complete();
                    return;
                }
                
                // 3. SQL 修饰
                sql = sqlQueryBuilder.buildChartSql(sql, request.getChartType());
                sql = sqlQueryBuilder.addTimeFilter(sql, request.getTimeRange());
                sql = sqlQueryBuilder.addLimit(sql, request.getMaxRecords());
                emitter.send(SseEmitter.event().name("sql_optimized").data("SQL 已优化"));
                
                // 4. 执行查询
                emitter.send(SseEmitter.event().name("query_execution").data("正在执行数据库查询..."));
                List<Map<String, Object>> data = dataQueryExecutor.executeQuery(sql);
                emitter.send(SseEmitter.event().name("query_completed").data("查询完成，返回 " + data.size() + " 条记录"));
                
                // 5. 先发送数据，让前端可以开始渲染表格
                Map<String, Object> dataResult = new HashMap<>();
                dataResult.put("data", data);
                dataResult.put("sql", Boolean.TRUE.equals(request.getIncludeSql()) ? sql : null);
                dataResult.put("totalRows", data.size());
                dataResult.put("usedLLM", sql != null && !sql.equals(sqlQueryBuilder.buildSqlFromNaturalLanguage(request.getQuery())));
                emitter.send(SseEmitter.event().name("data_ready").data(dataResult));
                
                // 6. 先生成总结（流式输出）- 调整顺序
                String insights = null;
                if (Boolean.TRUE.equals(request.getIncludeSummary())) {
                    emitter.send(SseEmitter.event().name("summary_generation").data("正在生成数据洞察..."));
                    insights = generateSummaryWithLLM(request.getQuery(), data);
                    if (insights != null) {
                        emitter.send(SseEmitter.event().name("summary_ready").data(insights));
                    }
                }
                
                // 7. 智能判断是否需要生成图表（后执行）
                QuestionAnalyzer.QuestionAnalysisResult analysisResult = questionAnalyzer.analyzeQuestion(request.getQuery());
                log.info("问题分析结果: 问题='{}', 类型='{}', 需要图表={}, 推荐类型='{}'", 
                    analysisResult.getQuestion(), analysisResult.getQuestionType().getDisplayName(), 
                    analysisResult.isNeedsChart(), analysisResult.getRecommendedChartType());
                
                if (analysisResult.isNeedsChart()) {
                    // 需要图表：生成图表配置
                    emitter.send(SseEmitter.event().name("chart_generation").data("正在生成图表配置..."));
                    
                    // 如果用户没有指定图表类型，使用推荐的类型
                    String chartType = request.getChartType();
                    if (chartType == null || chartType.trim().isEmpty()) {
                        chartType = analysisResult.getRecommendedChartType();
                        log.info("用户未指定图表类型，使用推荐类型: {}", chartType);
                    }
                    
                    String chartConfig = chartGenerator.generateChartConfig(data, chartType, request.getQuery());
                    emitter.send(SseEmitter.event().name("chart_ready").data(chartConfig));
                    
                    // 发送图表分析信息
                    Map<String, Object> chartAnalysis = new HashMap<>();
                    chartAnalysis.put("questionType", analysisResult.getQuestionType().getDisplayName());
                    chartAnalysis.put("recommendedChartType", analysisResult.getRecommendedChartType());
                    chartAnalysis.put("analysis", analysisResult.getAnalysis());
                    emitter.send(SseEmitter.event().name("chart_analysis").data(chartAnalysis));
                } else {
                    // 不需要图表：跳过图表生成
                    Map<String, Object> chartSkipped = new HashMap<>();
                    chartSkipped.put("reason", "此问题类型无需图表展示");
                    chartSkipped.put("questionType", analysisResult.getQuestionType().getDisplayName());
                    chartSkipped.put("analysis", analysisResult.getAnalysis());
                    emitter.send(SseEmitter.event().name("chart_skipped").data(chartSkipped));
                }
                
                // 8. 保存对话到Session
                saveConversationToSession(request, sql, data, insights);
                
                // 9. 发送完成事件
                emitter.send(SseEmitter.event().name("complete").data("所有处理完成"));
                emitter.complete();
                
            } catch (Exception e) {
                log.error("流式 BI 查询处理失败: {}", e.getMessage(), e);
                try {
                    emitter.send(SseEmitter.event().name("error").data("查询处理失败: " + e.getMessage()));
                    emitter.complete();
                } catch (IOException ex) {
                    log.error("发送错误事件失败", ex);
                    emitter.completeWithError(ex);
                }
            }
        });
        
        return emitter;
    }
    
    @Override
    public Map<String, Object> getHealthStatus() {
        Map<String, Object> status = new java.util.HashMap<>();
        
        try {
            boolean dbConnected = dataQueryExecutor.checkConnection();
            status.put("database", dbConnected ? "connected" : "disconnected");
            
            LLMClient client = llmClientFactory.createClient("deepseek");
            boolean aiAvailable = client.isAvailable();
            status.put("ai_service", aiAvailable ? "available" : "unavailable");
            
            status.put("overall", dbConnected && aiAvailable ? "healthy" : "unhealthy");
            status.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            log.error("健康检查失败: {}", e.getMessage());
            status.put("overall", "error");
            status.put("error", e.getMessage());
        }
        
        return status;
    }
    
    /**
     * 使用 LLM 生成 SQL（带系统提示与表结构），失败返回 null
     */
    private String generateSqlWithLLM(String userQuery, String timeRange, Integer maxRecords) {
        return generateSqlWithLLM(userQuery, timeRange, maxRecords, null);
    }
    
    /**
     * 使用 LLM 生成 SQL（带对话历史），失败返回 null
     */
    private String generateSqlWithLLM(String userQuery, String timeRange, Integer maxRecords, List<ChatRequest.ChatMessage> history) {
        try {
            LLMClient client = llmClientFactory.createClient("deepseek");
            if (client == null || !client.isAvailable()) {
                log.warn("LLM 客户端不可用，跳过 LLM 生成");
                return null;
            }
            String systemPrompt = biPromptProvider.loadSystemPrompt();
            String schemaJson = biPromptProvider.loadSchemaSnapshot();

            // 将 schema 注入提示词占位符
            String finalSystemPrompt = systemPrompt.replace("{{SCHEMA_JSON}}", schemaJson);
            
            // 如果有对话历史，添加到系统提示中
            if (history != null && !history.isEmpty()) {
                StringBuilder contextBuilder = new StringBuilder();
                contextBuilder.append("\n\n# 对话历史（用于理解上下文）\n");
                for (ChatRequest.ChatMessage msg : history) {
                    contextBuilder.append(msg.getRole()).append(": ").append(msg.getContent()).append("\n");
                }
                contextBuilder.append("\n# 当前查询\n");
                finalSystemPrompt += contextBuilder.toString();
            }

            // 将用户查询补充时间与限制的期望（减少幻觉）
            String normalizedQuery = userQuery;
            if (timeRange != null && !timeRange.isBlank()) {
                normalizedQuery += "（时间范围：" + timeRange + ")";
            }
            if (maxRecords != null && maxRecords > 0) {
                normalizedQuery += "（最大记录数：" + maxRecords + ")";
            }

            ChatRequest chatReq = new ChatRequest();
            chatReq.setMessage(normalizedQuery);
            chatReq.setSystemPrompt(finalSystemPrompt);
            
            // 设置对话历史
            if (history != null && !history.isEmpty()) {
                chatReq.setHistory(history);
            }

            ChatResponse chatRes = client.chat(chatReq);
            if (chatRes == null || chatRes.getContent() == null) {
                log.warn("LLM 返回为空");
                return null;
            }
            String sql = chatRes.getContent().trim();
            // 去除可能的代码块包裹
            if (sql.startsWith("```") && sql.endsWith("```")) {
                sql = sql.substring(3, sql.length() - 3).trim();
            }
            // 简单清洗多行
            sql = sql.replaceAll("^SQL\\s*[:：]", "").trim();
            return sql;
        } catch (Exception e) {
            log.warn("LLM 生成 SQL 异常: {}", e.getMessage());
            return null;
        }
    }

    private String generateSummaryWithLLM(String userQuery, List<Map<String, Object>> data) {
        try {
            LLMClient client = llmClientFactory.createClient("deepseek");
            if (client == null || !client.isAvailable()) {
                log.warn("LLM 客户端不可用，跳过总结生成");
                return null;
            }
            String prompt = biPromptProvider.loadSummaryPrompt();
            String dataSnippet = buildDataSnippet(data, 50, 8); // 取前 50 行，最多 8 列
            String systemPrompt = prompt
                .replace("{USER_QUERY}", safe(userQuery))
                .replace("{DATA_SNIPPET}", dataSnippet);

            ChatRequest chatReq = new ChatRequest();
            chatReq.setMessage("请基于上述输入给出中文结论");
            chatReq.setSystemPrompt(systemPrompt);
            ChatResponse res = client.chat(chatReq);
            return res != null ? res.getContent() : null;
        } catch (Exception e) {
            log.warn("LLM 生成总结异常: {}", e.getMessage());
            return null;
        }
    }

    private String buildDataSnippet(List<Map<String, Object>> data, int maxRows, int maxCols) {
        if (data == null || data.isEmpty()) return "(无数据)";
        List<String> lines = data.stream().limit(maxRows).map(row -> {
            return row.entrySet().stream().limit(maxCols)
                .map(e -> e.getKey() + ":" + String.valueOf(e.getValue()))
                .collect(Collectors.joining(", "));
        }).collect(Collectors.toList());
        return String.join("\n", lines);
    }

    private String safe(String s) { return s == null ? "" : s; }
    
    /**
     * 保存对话到Session
     */
    private void saveConversationToSession(BiQueryRequest request, String sql, List<Map<String, Object>> data, String insights) {
        try {
            if (request.getSessionId() == null) {
                log.warn("SessionId为空，跳过保存对话");
                return;
            }
            
            // 保存用户消息
            ChatRequest.ChatMessage userMessage = new ChatRequest.ChatMessage();
            userMessage.setRole("user");
            userMessage.setContent(request.getQuery());
            userMessage.setTimestamp(System.currentTimeMillis());
            sessionService.addMessage(request.getSessionId(), userMessage);
            
            // 构建AI回复内容
            StringBuilder aiResponse = new StringBuilder();
            aiResponse.append("查询结果：\n");
            aiResponse.append("- 返回数据：").append(data.size()).append(" 条记录\n");
            if (sql != null) {
                aiResponse.append("- SQL语句：").append(sql).append("\n");
            }
            if (insights != null) {
                aiResponse.append("- 数据洞察：").append(insights);
            }
            
            // 保存AI回复
            ChatRequest.ChatMessage aiMessage = new ChatRequest.ChatMessage();
            aiMessage.setRole("assistant");
            aiMessage.setContent(aiResponse.toString());
            aiMessage.setTimestamp(System.currentTimeMillis());
            sessionService.addMessage(request.getSessionId(), aiMessage);
            
            log.debug("已保存对话到会话: {}", request.getSessionId());
            
        } catch (Exception e) {
            log.error("保存对话到Session失败: {}", e.getMessage(), e);
        }
    }
}
